﻿using Cyss.Core.Infrastructure;
using Cyss.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Globalization;

namespace Cyss.Core
{
    /// <summary>
    /// json扩展
    /// </summary>
    public static class JsonExtensions
    {
        /// <summary>
        /// 属性是否存在
        /// </summary>
        /// <param name="jsonElement"></param>
        /// <param name="PropertyName"></param>
        /// <returns></returns>
        public static bool HasProperty(this JsonElement jsonElement, string PropertyName)
        {
            try
            {
                jsonElement.GetProperty(PropertyName);
                return true;
            }
            catch (KeyNotFoundException ex)
            {
                return false;
            }
        }

      

    }

    /// <summary>
    /// EncryptString 类型自定义解析,序列化的时候加密,反序列化时解密 
    /// </summary>
    public class EncryptStringJsonConverter : JsonConverter<EncryptString>
    {
        /// <summary>
        /// 读取
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="typeToConvert"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public override EncryptString Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            EncryptString encryptString = new EncryptString();
            encryptString = EncryptHelper.CustomDecrypt(reader.GetString());
            return encryptString;
        }

        /// <summary>
        /// 写入
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="value"></param>
        /// <param name="options"></param>
        public override void Write(Utf8JsonWriter writer, EncryptString value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(EncryptHelper.CustomEncrypt(value));
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public class OperateResultJsonConverterFactory : JsonConverterFactory
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="typeToConvert"></param>
        /// <returns></returns>
        public override bool CanConvert(Type typeToConvert)
        {
            if (typeToConvert.IsGenericType && typeof(OperateResult<>) == typeToConvert.GetGenericTypeDefinition())
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="typeToConvert"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
        {
            Type keyType = typeToConvert.GetGenericArguments()[0];

            JsonConverter converter = (JsonConverter)Activator.CreateInstance(
                typeof(OperateResultJsonConverter<>).MakeGenericType(
                    new Type[] { keyType }), options);

            return converter;
        }
    }

    /// <summary>
    /// EncryptString 类型自定义解析,序列化的时候加密,反序列化时解密 
    /// </summary>
    public class OperateResultJsonConverter<T> : JsonConverter<OperateResult<T>>
    {
        private readonly JsonConverter<T> _valueConverter;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="options"></param>
        public OperateResultJsonConverter(JsonSerializerOptions options)
        {
            // For performance, use the existing converter if available.
            _valueConverter = (JsonConverter<T>)options
                .GetConverter(typeof(T));
        }

        /// <summary>
        /// 读取
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="typeToConvert"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public override OperateResult<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            var value = new OperateResult<T>();
            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.EndObject)
                {
                    return value;
                }

                // Get the key.
                if (reader.TokenType != JsonTokenType.PropertyName)
                {
                    throw new JsonException();
                }

                string propertyName = reader.GetString();

                reader.Read();
                switch (propertyName)
                {
                    case "IsSuccess":
                        value.IsSuccess = reader.GetBoolean();
                        break;
                    case "IsZip":
                        value.IsZip = reader.GetBoolean();
                        break;
                    case "IsEncryption":
                        value.IsEncryption = reader.GetBoolean();
                        break;
                    case "Message":
                        value.Message = reader.GetString();
                        break;
                    case "Code":
                        value.Code = reader.GetInt32();
                        break;
                    case "Data":
                        if (value.IsZip || value.IsEncryption)
                        {
                            string tv = reader.GetString();
                            if (value.IsZip)
                            {
                                tv = tv.UnZipString();
                            }
                            if (value.IsEncryption)
                            {
                                tv = EncryptHelper.CustomDecrypt(tv);
                            }
                            value.Data = JsonSerializer.Deserialize<T>(tv, options);
                        }
                        else
                        {
                            value.Data = JsonSerializer.Deserialize<T>(ref reader, options);

                        }
                        break;
                }

            }
            return value;
        }

        /// <summary>
        /// 写入
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="value"></param>
        /// <param name="options"></param>
        public override void Write(Utf8JsonWriter writer, OperateResult<T> value, JsonSerializerOptions options)
        {
            writer.WriteStartObject();
            writer.WriteBoolean("IsSuccess", value.IsSuccess);
            writer.WriteBoolean("IsZip", value.IsZip);
            writer.WriteBoolean("IsEncryption", value.IsEncryption);
            writer.WriteString("Message", value.Message);
            writer.WriteNumber("Code", value.Code);
            writer.WriteString("ResponseString", value.ResponseString);
            string tv = JsonHelper.SerializeObject(value.Data);

            if (value.IsEncryption || value.IsZip)
            {
                if (value.IsEncryption)
                {
                    tv = EncryptHelper.CustomEncrypt(tv);
                }
                if (value.IsZip)
                {
                    tv = tv.ZipString();
                }
                writer.WriteString("Data", tv);
            }
            else
            {
                writer.WritePropertyName("Data");
                JsonSerializer.Serialize(writer, value.Data, options);
            }

            writer.WriteEndObject();
        }


    }

    /// <summary>
    /// 
    /// </summary>
    public class DatetimeJsonConverter : JsonConverter<DateTime>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="typeToConvert"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String)
            {
                if (DateTime.TryParse(reader.GetString(), out DateTime date))
                    return date;
            }
            return reader.GetDateTime();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="value"></param>
        /// <param name="options"></param>
        public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value);
        }
    }

    public class JsonTimeSpanConverter : JsonConverter<TimeSpan>
    {
        public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType== JsonTokenType.String)
            {
                return TimeSpan.ParseExact(reader.GetString(), "c", CultureInfo.InvariantCulture);
            }
            // 使用常量 "c" 來指定用 [-][d.]hh:mm:ss[.fffffff] 作为 TimeSpans 转换的格式
            return new TimeSpan(0, 0, 0);
        }
        public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString("c", CultureInfo.InvariantCulture));
        }
    }
}
